#if !defined(PORTABLE_TIMING_H)
#define PORTABLE_TIMING_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#if !defined(_MSC_VER)
#define _timeb timeb
#define _ftime ftime
#endif



// for timing
#include <sys/timeb.h>
#include <time.h>
#include <math.h>
#include <iomanip>
#include <string>
#include <sstream>
#include <iostream>

struct t_portable_timer
{
	_timeb timebuffer;
	t_portable_timer() {_ftime( &timebuffer);}
	double reset();
	inline std::string pretty_reset(unsigned precision = 1);
	static std::string pretty_time(double seconds, unsigned precision = 1);
};

inline double t_portable_timer::reset()
{
	// print out how long it took
	_timeb oldtimebuffer = timebuffer;
	_ftime( &timebuffer);
	double oldtime = oldtimebuffer.time + oldtimebuffer.millitm / 1000.0;
	double newtime = timebuffer.time + timebuffer.millitm / 1000.0;
	//std::cerr << (newtime - oldtime)  << std::endl;
	return newtime - oldtime;
}

inline std::string t_portable_timer::pretty_reset(unsigned precision)
{
	// print out how long it took
	double seconds = reset();
	//std::cerr << seconds  << std::endl;
	//std::cerr << "seconds= " << 1.0 << " " << seconds << std::endl;
	return pretty_time(seconds, precision);
}

inline std::string t_portable_timer::pretty_time(double seconds, unsigned precision)
{
	std::ostringstream ostrm;
	ostrm.precision(precision);
	if (seconds < 60)
	{
		//std::cerr << ":seconds = " << seconds << "\n";
		ostrm << std::fixed << std::setw(precision + 3) << seconds << " s";
	}
	else if (seconds < 3600)
	{
		int minutes = (int) (seconds / 60.0);
		//std::cerr << "minutes = " << seconds << "\n";
		ostrm   << std::setw(2)
				<< minutes						<< " min "
				<< std::fixed << std::setw(4)
				<< ( seconds - minutes * 60.0)	<< " s";
	}
	else
	{
		//std::cerr << "hours = " << seconds << "\n";
		int hours = (int) (seconds / 3600.0);
		ostrm	<< hours						<< " hrs "
				<< std::fixed << std::setw(2)
				<< ( (seconds / 60.0) - hours * 60.0)	<< " min";
	}
	return ostrm.str();
}
//_______________________________________________________________________________________
//
//	output operator
//_______________________________________________________________________________________
template <typename os_>
os_& operator << (os_& os, const t_portable_timer& timer)
{
	// print out how long it took
	_timeb newtimebuffer;
	_ftime( &newtimebuffer);
	double oldtime = timer.timebuffer.time + timer.timebuffer.millitm / 1000.0;
	double newtime = newtimebuffer.time + newtimebuffer.millitm / 1000.0;
	os << std::setprecision(4) << std::fixed << newtime - oldtime << " seconds";
	return os;
}
#endif
